#pragma once

#include<iostream>
#include <memory>
#include<sys/epoll.h>
#include "InetAddr.hpp"
#include "Socket.hpp"
#include "Log.hpp"
#include"IOServer.hpp"
#include "EpollServer.hpp"

using namespace SocketModule;
using namespace LogModule;
//负责获取连接模块
class Listener : public Connection
{
public:
    Listener(uint16_t port):_listensock(std::make_unique<TcpSocket>()), _port(port)
    {
        _listensock->BuildTcpSocketMethod(_port);
        SetSockfd(_listensock->Fd());
        SetEvents(EPOLLIN | EPOLLET);
    }
    virtual void _Recver() override
    {
        //读事件,listensock就绪
        //进行IO处理, 获取新连接
        while(1)
        {
            InetAddr peer;
            int aerrno = 0;
            SockPtr sockfd = _listensock->Accepter(&peer, &aerrno);
            if(sockfd->Fd())
            {
                //success
                LOG(LogLevel::DEBUG)<<"Accepter success" << sockfd;
                //设置非阻塞
                SetNonBlock(sockfd->Fd());
                //sockfd包装成connection
                auto conn = std::make_shared<IOServer>(sockfd->Fd());
                //插入到epollserver
                GetOwner()->InsertConnection(conn);
            }
            else
            {
                if(aerrno == EAGAIN || aerrno == EWOULDBLOCK)
                {
                    LOG(LogLevel::DEBUG)<<"accepter all connection ... done";//连接获取完了
                    break;
                }
                else if(aerrno == EINTR){
                    LOG(LogLevel::DEBUG)<<"accepter intr by signal, continue";//被信号中断
                    continue;
                }
                else{
                    LOG(LogLevel::DEBUG)<<"accepter error ... ignore";
                    break;
                }
            }
        }
    }
    virtual void _Sender() override
    {}
    virtual void _Excepter() override
    {} 
    int SockFd(){return _listensock->Fd();}
    //我们吧listenfd封装成一个Connection，托管给EpollServer
    ~Listener()
    {
        _listensock->Close();
    }
private:
    std::unique_ptr<Socket> _listensock;
    uint16_t _port;
};